﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;

namespace Kay.Client.Demo
{
    public partial class StartUp : Form
    {
        public string Ip { get; set; }

        public ushort Port { get; set; }

        public string UserName { get; set; }

        public string Password { get; set; }

        private TcpInterNetworkStreamClient _client;

        private Dictionary<string, Chat> _chatForms = new Dictionary<string, Chat>();

        private Broadcast _broadcast = null;

        public StartUp()
        {
            InitializeComponent();
        }

        private void StartUp_Load(object sender, EventArgs e)
        {
            Application.DoEvents();
            _client = new TcpInterNetworkStreamClient(UserName, Password, Ip, Port);

            _client.TextMessageReceived += OnClientTextMessageReceived;
            _client.RequestSendFile += OnClientRequestSendFile;
            _client.ReciveFileComplete += OnClientReciveFileComplete;
            _client.SendFileComplete += OnClientSendFileComplete;
            _client.SendFileProgressChanged += OnClientSendFileProgressChanged;
            _client.ReciveFileProgressChanged += OnClientReciveFileProgressChanged;
            _client.IsRuningChanged += OnClientIsRuningChanged;
            _client.UpdateUsersComplete += OnClientUpdateUsersComplete;
            _client.ContactsConnected += OnClientContactsConnected;
            _client.ContactsOffline += OnClientContactsOffline;
            _client.TransferFileUserOffline += OnClientTransferFileUserOffline;
            _client.BroadcastTextMessageReceived += OnClientBroadcastTextMessageReceived;
            _client.ContactsAgreeReciveFile += OnClientContactsAgreeReciveFile;

            if (_client.Start())
                _client.UpdateUsers();
            else
            {
                MessageBox.Show(this, @"登录服务器失败！", @"错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                Enabled = true;
            }
        }

        private void OnClientContactsAgreeReciveFile(object sender, FileMessageReceivedEventArgs e)
        {
            if (InvokeRequired)
            {
                Invoke(new Action<object, FileMessageReceivedEventArgs>(OnClientContactsAgreeReciveFile), sender, e);
                return;
            }
            if (_chatForms.ContainsKey(e.TransferFileInfo.ReceiveUserId))
            {
                _chatForms[e.TransferFileInfo.ReceiveUserId].ContactsAgreeReciveFile(e.UserInfo, e.TransferFileInfo);
            }
            else
            {
                var chat = new Chat(e.UserInfo, _client);
                chat.Closed += OnChatClosed;
                _chatForms.Add(e.UserInfo.Id, chat);
                chat.Show();
                _chatForms[e.UserInfo.Id].ContactsAgreeReciveFile(e.UserInfo, e.TransferFileInfo);
            }
        }

        private void OnClientBroadcastTextMessageReceived(object sender, TextMessageReceivedEventArgs e)
        {
            if (InvokeRequired)
            {
                Invoke(new Action<object, TextMessageReceivedEventArgs>(OnClientBroadcastTextMessageReceived), sender, e);
                return;
            }
            if (_broadcast == null || _broadcast.IsDisposed)
            {
                _broadcast = new Broadcast(_client);
                _broadcast.Show();
            }
            _broadcast.ReceivedText(e.UserInfo.Name, e.Text);
        }

        private void OnClientTransferFileUserOffline(object sender, ContactsInfoEventArgs e)
        {
            if (_chatForms.ContainsKey(e.UserInfo.Id))
            {
                _chatForms[e.UserInfo.Name].FileComplate(e.UserInfo.Id);
            }
        }

        private void OnClientSendFileComplete(object sender, FileMessageReceivedEventArgs e)
        {
            if (InvokeRequired)
            {
                Invoke(new Action<object, FileMessageReceivedEventArgs>(OnClientSendFileComplete), sender, e);
                return;
            }
            if (_chatForms.ContainsKey(e.UserInfo.Id))
            {
                _chatForms[e.UserInfo.Id].FileComplate(e.TransferFileInfo.SendId);
            }
            Activate();
            MessageBox.Show(this,
                string.Format("向 {0} 发送文件完成！{1}文件名：{2}", e.UserInfo.Name, Environment.NewLine,
                    Path.GetFileName(e.TransferFileInfo.SourceFileName)), @"提示", MessageBoxButtons.OK,
                MessageBoxIcon.Information);
        }

        private void OnClientReciveFileComplete(object sender, FileMessageReceivedEventArgs e)
        {
            if (InvokeRequired)
            {
                Invoke(new Action<object, FileMessageReceivedEventArgs>(OnClientReciveFileComplete), sender, e);
                return;
            }
            if (_chatForms.ContainsKey(e.UserInfo.Id))
            {
                _chatForms[e.UserInfo.Id].FileComplate(e.TransferFileInfo.SendId);
            }
            Activate();
            MessageBox.Show(this,
                string.Format("接收 {0} 的文件完成！{1}文件名：{2}", e.UserInfo.Name, Environment.NewLine,
                    Path.GetFileName(e.TransferFileInfo.SourceFileName)), @"提示", MessageBoxButtons.OK,
                MessageBoxIcon.Information);
        }

        private void OnClientSendFileProgressChanged(object sender, ProgressIsChangedEventArgs e)
        {
            if (_chatForms.ContainsKey(e.Project.ReceiveUserId))
            {
                _chatForms[e.Project.ReceiveUserId].FileProgressChanged(e.Project.SendId, e.Progress);
            }
        }

        private void OnClientReciveFileProgressChanged(object sender, ProgressIsChangedEventArgs e)
        {
            if (_chatForms.ContainsKey(e.Project.SendUserId))
            {
                _chatForms[e.Project.SendUserId].FileProgressChanged(e.Project.SendId, e.Progress);
            }
        }

        private bool OnClientRequestSendFile(object sender, FileMessageReceivedEventArgs e)
        {
            if (InvokeRequired)
            {
                var r = Invoke(new Func<object, FileMessageReceivedEventArgs, bool>(OnClientRequestSendFile), sender, e);
                return (bool)r;
            }
            Activate();
            if (MessageBox.Show(this,
                    string.Format("是否接受 {0} 发送的文件？{1}文件名：{2}", e.UserInfo.Name, Environment.NewLine,
                        Path.GetFileName(e.TransferFileInfo.SourceFileName)), @"提示", MessageBoxButtons.YesNo,
                    MessageBoxIcon.Information) !=
                DialogResult.Yes)
                return false;
            if (_chatForms.ContainsKey(e.UserInfo.Id))
            {
                _chatForms[e.UserInfo.Id].ReceivedRequestSendFile(e.UserInfo, e.TransferFileInfo);
            }
            else
            {
                var chat = new Chat(e.UserInfo, _client);
                chat.Closed += OnChatClosed;
                _chatForms.Add(e.UserInfo.Id, chat);
                chat.Show();
                _chatForms[e.UserInfo.Id].ReceivedRequestSendFile(e.UserInfo, e.TransferFileInfo);
            }
            return true;
        }

        private void OnClientTextMessageReceived(object sender, TextMessageReceivedEventArgs e)
        {
            if (InvokeRequired)
            {
                Invoke(new Action<object, TextMessageReceivedEventArgs>(OnClientTextMessageReceived), sender, e);
                return;
            }
            if (_chatForms.ContainsKey(e.UserInfo.Id))
            {
                _chatForms[e.UserInfo.Id].ReceivedText(e.Text);
                _chatForms[e.UserInfo.Id].Activate();
            }
            else
            {
                var chat = new Chat(e.UserInfo, _client);
                chat.Closed += OnChatClosed;
                _chatForms.Add(e.UserInfo.Id, chat);
                chat.Show();
                _chatForms[e.UserInfo.Id].ReceivedText(e.Text);
            }
        }

        private void OnChatClosed(object sender, EventArgs e)
        {
            var chat = (Chat)sender;
            _chatForms.Remove(chat.ContactsInfo.Id);
            GC.Collect();
        }

        private void OnClientContactsOffline(object sender, ContactsInfoEventArgs e)
        {
            if (flowLayoutPanel_Users.InvokeRequired)
            {
                flowLayoutPanel_Users.Invoke(new Action<object, ContactsInfoEventArgs>(OnClientContactsOffline), sender,
                    e);
            }
            else
            {
                UserInfo u = null;
                foreach (Control control in flowLayoutPanel_Users.Controls)
                {
                    var info = control as UserInfo;
                    if (info == null)
                        continue;
                    if (info.ContactsInfo.Id != e.UserInfo.Id)
                        continue;
                    u = info;
                    break;
                }
                if (u != null)
                {
                    flowLayoutPanel_Users.Controls.Remove(u);
                    u.Dispose();
                }
                if (_chatForms.ContainsKey(e.UserInfo.Id))
                {
                    _chatForms[e.UserInfo.Id].Close();
                    _chatForms.Remove(e.UserInfo.Id);
                }
                GC.Collect();
            }
        }

        private void OnClientContactsConnected(object sender, ContactsInfoEventArgs e)
        {
            if (flowLayoutPanel_Users.InvokeRequired)
            {
                flowLayoutPanel_Users.Invoke(new Action<object, ContactsInfoEventArgs>(OnClientContactsConnected),
                    sender, e);
            }
            else
            {
                if (e.UserInfo.Id == _client.OwnUserInfo.Id)
                    return;
                var user = new UserInfo(e.UserInfo);
                user.DoubleClick += OnUserInfoDoubleClick;
                flowLayoutPanel_Users.Controls.Add(user);
            }
        }

        private void OnClientUpdateUsersComplete()
        {
            if (flowLayoutPanel_Users.InvokeRequired)
            {
                flowLayoutPanel_Users.Invoke(new Action(OnClientUpdateUsersComplete));
            }
            else
            {
                flowLayoutPanel_Users.Controls.Clear();
                GC.Collect();
                _client.Contacts.ForEach(u =>
                    {
                        if (u != null && u.Id != _client.OwnUserInfo.Id)
                        {
                            var user = new UserInfo(u);
                            user.DoubleClick += OnUserInfoDoubleClick;
                            flowLayoutPanel_Users.Controls.Add(user);
                        }
                    });
                Enabled = true;
            }
        }

        private void OnUserInfoDoubleClick(object sender, EventArgs e)
        {
            var user = (UserInfo)sender;
            if (_chatForms.ContainsKey(user.ContactsInfo.Id))
            {
                _chatForms[user.ContactsInfo.Id].Activate();
                return;
            }
            var chat = new Chat(user.ContactsInfo, _client);
            chat.Closed += OnChatClosed;
            _chatForms.Add(user.ContactsInfo.Id, chat);
            chat.Show();
        }

        private void OnClientIsRuningChanged(bool obj)
        {
            if (menuStrip.InvokeRequired)
            {
                menuStrip.Invoke(new Action<bool>(OnClientIsRuningChanged), obj);
                return;
            }
            toolStripMenuItem_Start.Enabled = !obj;
        }

        private void toolStripMenuItem_Quit_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void StartUp_FormClosed(object sender, FormClosedEventArgs e)
        {
            if (_client != null)
                _client.Stop();
        }

        private void toolStripMenuItem_Bran_Click(object sender, EventArgs e)
        {
            if (_broadcast == null || _broadcast.IsDisposed)
            {
                _broadcast = new Broadcast(_client);
                _broadcast.Show();
            }
            else
            {
                _broadcast.Activate();
            }
        }

        private void toolStripMenuItem_Start_Click(object sender, EventArgs e)
        {
            Enabled = false;
            if (_client.Start())
                _client.UpdateUsers();
            else
            {
                MessageBox.Show(this, @"登录服务器失败！", @"错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                Enabled = true;
            }
        }
    }
}
